/**
 * 火山引擎流式语音合成服务
 * 封装了TTS流式API请求、参数构建、音频处理和错误处理
 * 专为微信小程序环境优化
 */
export default class TTSStreamService {
  constructor(options = {}) {
    // 初始化配置
    this.appId = options.appId;
    this.accessKey = options.accessKey;
    this.resourceId = options.resourceId || 'volc.service_type.10029'; // 默认资源ID
    this.speaker = options.speaker || 'zh_female_wanqudashu_moon_bigtts'; // 默认音色
    this.apiUrl = 'https://openspeech.bytedance.com/api/v3/tts/unidirectional';
    
    // 音频缓存
    this.audioCache = {};
    this.tempFiles = [];
    
    // 状态变量
    this.isStreaming = false;
    this.isPlaying = false;
    this.currentStreamId = null;
    this.currentAudioContext = null;
    this.audioChunks = [];
    
    // 回调函数
    this.callbacks = {
      onStart: options.onStart || null, // 开始播放回调
      onData: options.onData || null, // 数据到达回调
      onEnd: options.onEnd || null, // 播放结束回调
      onError: options.onError || null, // 错误回调
      onSegmentEnd: options.onSegmentEnd || null // 分段播放结束回调
    };
    
    console.log('[TTSStreamService] 服务初始化完成');
  }
  
  /**
   * 生成UUID，用于请求追溯
   */
  generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      const r = Math.random() * 16 | 0;
      const v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }
  
  /**
   * 设置回调函数
   * @param {Object} callbacks - 包含各种事件回调的对象
   */
  setCallbacks(callbacks = {}) {
    this.callbacks = {
      ...this.callbacks,
      ...callbacks
    };
  }
  
  /**
   * 构建请求参数
   * @param {string} text - 要合成的文本
   * @param {string} uid - 用户ID，用于缓存和追踪
   * @returns {Object} - 请求参数对象
   */
  buildRequestPayload(text, uid) {
    // 自定义参数
    const additions = {
      disable_markdown_filter: true,
      enable_language_detector: true,
      enable_latex_tn: true,
      disable_default_bit_rate: true,
      max_length_to_filter_parenthesis: 0,
      cache_config: {
        text_type: 1,
        use_cache: true
      }
    };

    return {
      user: { uid: uid || this.generateUUID().substring(0, 8) },
      req_params: {
        text: text,
        speaker: this.speaker,
        additions: JSON.stringify(additions),
        audio_params: {
          format: 'mp3',
          sample_rate: 16000, // 降低采样率，减小文件大小
          bit_rate: 32000,    // 降低比特率，减小文件大小
          compression_ratio: 1.0, // 最大压缩比
          speed: 1.0,
          volume: 1.0
        }
      }
    };
  }
  
  /**
   * 流式合成语音
   * @param {string} text - 要合成的文本
   * @param {string} messageId - 消息ID，用于缓存
   * @param {boolean} silent - 是否静默模式（不显示加载提示）
   * @returns {Promise<Array>} - 音频数据块数组
   */
  streamSynthesize(text, messageId, silent = false) {
    return new Promise((resolve, reject) => {
      // 如果已经在流式合成，先停止当前的
      if (this.isStreaming) {
        this.stopStreaming();
      }
      
      // 设置新的流ID和状态
      this.currentStreamId = messageId || this.generateUUID();
      this.isStreaming = true;
      this.audioChunks = [];
      
      if (!silent) {
        wx.showLoading({ title: '语音合成中...' });
      }
      
      // 构建请求头
      const headers = {
        'X-Api-App-Id': this.appId,
        'X-Api-Access-Key': this.accessKey,
        'X-Api-Resource-Id': this.resourceId,
        'X-Api-App-Key': 'aGjiRDfUWi',
        'Content-Type': 'application/json',
        'Connection': 'keep-alive',
        'X-Api-Request-Id': this.generateUUID()
      };
      
      // 构建请求体
      const payload = this.buildRequestPayload(text, this.currentStreamId);
      
      console.log('[TTSStreamService] 开始请求TTS服务, 文本长度:', text.length);
      
      // 使用wx.request进行请求
      wx.request({
        url: this.apiUrl,
        method: 'POST',
        header: headers,
        data: payload,
        responseType: 'text', // 设置为text以获取原始响应
        success: (res) => {
          if (res.statusCode === 200 && res.data) {
            try {
              // 检查是否是字符串响应（包含多个JSON对象）
              if (typeof res.data === 'string') {
                // 按行分割响应
                const lines = res.data.split('\n').filter(line => line.trim());
                console.log(`[TTSStreamService] 收到${lines.length}行数据`);
                
                // 处理每一行JSON数据
                for (let i = 0; i < lines.length; i++) {
                  const line = lines[i];
                  try {
                    const data = JSON.parse(line);
                    
                    // 处理音频数据
                    if (data.code === 0 && data.data) {
                      // 确保Base64数据格式正确
                      let audioChunk = data.data;
                      
                      // 检查并修复Base64数据
                      if (audioChunk.startsWith('data:audio')) {
                        // 如果是data URI格式，提取Base64部分
                        audioChunk = audioChunk.split(',')[1];
                      }
                      
                      // 添加到音频块数组
                      this.audioChunks.push(audioChunk);
                      
                      // 触发数据回调
                      if (this.callbacks.onData) {
                        this.callbacks.onData(audioChunk);
                      }
                    } 
                    // 处理合成结束标志
                    else if (data.code === 20000000) {
                      console.log('[TTSStreamService] 语音合成完成');
                      
                      // 缓存完整的音频数据
                      if (messageId && this.audioChunks.length > 0) {
                        this.audioCache[messageId] = this.audioChunks.join('');
                      }
                      
                      if (!silent) {
                        wx.hideLoading();
                      }
                      
                      // 结束流式处理
                      this.isStreaming = false;
                      resolve(this.audioChunks);
                      return;
                    } 
                    // 处理错误
                    else if (data.code > 0) {
                      console.error('[TTSStreamService] 服务端返回错误:', data);
                      
                      if (!silent) {
                        wx.hideLoading();
                        wx.showToast({
                          title: `合成失败: ${this.getErrorMessage(data.code)}`,
                          icon: 'none',
                          duration: 3000
                        });
                      }
                      
                      // 结束流式处理
                      this.isStreaming = false;
                      reject({
                        code: data.code,
                        message: data.message || '服务端返回错误'
                      });
                      return;
                    }
                  } catch (error) {
                    console.warn('[TTSStreamService] 解析JSON失败:', error, line);
                  }
                }
                
                // 如果处理完所有行后仍在流式状态，则完成请求
                if (this.isStreaming && this.audioChunks.length > 0) {
                  console.log('[TTSStreamService] 所有数据处理完成，音频块数量:', this.audioChunks.length);
                  
                  // 缓存完整的音频数据
                  if (messageId) {
                    this.audioCache[messageId] = this.audioChunks.join('');
                  }
                  
                  if (!silent) {
                    wx.hideLoading();
                  }
                  
                  this.isStreaming = false;
                  resolve(this.audioChunks);
                } else if (this.isStreaming) {
                  // 没有收到有效音频数据
                  console.warn('[TTSStreamService] 未收到有效音频数据');
                  
                  if (!silent) {
                    wx.hideLoading();
                    wx.showToast({
                      title: '未收到有效音频数据',
                      icon: 'none'
                    });
                  }
                  
                  this.isStreaming = false;
                  reject({
                    code: 'NO_AUDIO_DATA',
                    message: '未收到有效音频数据'
                  });
                }
              } else {
                // 如果响应不是字符串，可能是直接返回了一个JSON对象
                console.error('[TTSStreamService] 非预期的响应格式:', res.data);
                
                if (!silent) {
                  wx.hideLoading();
                  wx.showToast({
                    title: '服务响应格式错误',
                    icon: 'none'
                  });
                }
                
                this.isStreaming = false;
                reject({
                  code: 'INVALID_RESPONSE',
                  message: '服务响应格式错误'
                });
              }
            } catch (error) {
              console.error('[TTSStreamService] 处理响应失败:', error);
              
              if (!silent) {
                wx.hideLoading();
                wx.showToast({
                  title: '处理响应失败',
                  icon: 'none'
                });
              }
              
              this.isStreaming = false;
              reject({
                code: 'PROCESSING_ERROR',
                message: '处理响应失败: ' + error.message
              });
            }
          } else {
            // HTTP错误
            console.error('[TTSStreamService] HTTP错误:', res.statusCode);
            
            if (!silent) {
              wx.hideLoading();
              wx.showToast({
                title: `请求失败: ${res.statusCode}`,
                icon: 'none'
              });
            }
            
            this.isStreaming = false;
            reject({
              code: 'HTTP_ERROR',
              message: `HTTP错误: ${res.statusCode}`
            });
          }
        },
        fail: (err) => {
          console.error('[TTSStreamService] 请求失败:', err);
          
          if (!silent) {
            wx.hideLoading();
            wx.showToast({
              title: '语音服务请求失败',
              icon: 'none'
            });
          }
          
          this.isStreaming = false;
          reject({
            code: 'REQUEST_ERROR',
            message: '请求失败: ' + (err.errMsg || '')
          });
        }
      });
    });
  }
  
  /**
   * 停止当前的流式合成
   */
  stopStreaming() {
    if (this.isStreaming) {
      this.isStreaming = false;
      this.currentStreamId = null;
      console.log('[TTSStreamService] 停止流式合成');
    }
    
    // 停止播放
    this.stopPlayback();
  }
  
  /**
   * 停止当前播放
   */
  stopPlayback() {
    if (this.isPlaying && this.currentAudioContext) {
      this.isPlaying = false;
      this.currentAudioContext.stop();
      this.currentAudioContext.destroy();
      this.currentAudioContext = null;
      console.log('[TTSStreamService] 停止音频播放');
    }
  }
  
  /**
   * 播放音频数据
   * @param {Array<string>} audioChunks - Base64编码的音频数据块数组
   * @returns {Promise<boolean>} - 是否成功播放
   */
  async playAudio(audioChunks) {
    console.log('[TTSStreamService] 开始播放音频, 块数:', audioChunks.length);
    
    if (!audioChunks || audioChunks.length === 0) {
      console.warn('[TTSStreamService] 没有音频数据可播放');
      return false;
    }
    
    try {
      // 如果有多个音频块，合并它们
      let combinedBase64 = '';
      let validChunksCount = 0;
      
      // 处理并合并所有块
      for (let i = 0; i < audioChunks.length; i++) {
        let chunk = audioChunks[i];
        
        // 跳过空块
        if (!chunk || chunk.trim() === '') {
          console.warn(`[TTSStreamService] 第${i+1}块是空的，跳过`);
          continue;
        }
        
        // 检查并修复每个块
        if (!this.isValidBase64(chunk)) {
          console.warn(`[TTSStreamService] 第${i+1}块音频数据无效，尝试修复`);
          chunk = this.fixBase64Padding(chunk);
          
          // 再次验证
          if (!this.isValidBase64(chunk)) {
            console.error(`[TTSStreamService] 无法修复第${i+1}块音频数据，跳过`);
            continue;
          }
        }
        
        // 累加有效的块
        combinedBase64 += chunk;
        validChunksCount++;
      }
      
      if (validChunksCount === 0) {
        console.error('[TTSStreamService] 没有有效的音频块可播放');
        return false;
      }
      
      console.log(`[TTSStreamService] 成功合并了${validChunksCount}个有效音频块`);
      
      // 最终验证合并后的数据
      if (!this.isValidBase64(combinedBase64)) {
        console.warn('[TTSStreamService] 合并后的音频数据无效，尝试修复');
        combinedBase64 = this.fixBase64Padding(combinedBase64);
        
        // 如果仍然无效，尝试只使用第一个有效块
        if (!this.isValidBase64(combinedBase64)) {
          console.warn('[TTSStreamService] 合并后的数据仍然无效，尝试使用第一个有效块');
          
          // 查找第一个有效块
          for (let i = 0; i < audioChunks.length; i++) {
            let chunk = audioChunks[i];
            if (chunk && chunk.trim() !== '') {
              chunk = this.fixBase64Padding(chunk);
              if (this.isValidBase64(chunk)) {
                console.log(`[TTSStreamService] 使用第${i+1}块作为备选方案`);
                combinedBase64 = chunk;
                break;
              }
            }
          }
        }
      }
      
      // 如果数据仍然无效，返回失败
      if (!combinedBase64 || !this.isValidBase64(combinedBase64)) {
        console.error('[TTSStreamService] 无法获取有效的Base64音频数据');
        return false;
      }
      
      // 使用临时文件播放
      return await this.playAudioWithTempFile(combinedBase64);
    } catch (error) {
      console.error('[TTSStreamService] 播放音频时出错:', error);
      return false;
    }
  }
  
  /**
   * 检查是否是有效的Base64字符串
   * @param {string} base64Data - Base64编码的字符串
   * @returns {boolean} - 是否有效
   * @private
   */
  isValidBase64(base64Data) {
    if (!base64Data || typeof base64Data !== 'string') {
      console.warn('[TTSStreamService] Base64数据为空或不是字符串');
      return false;
    }
    
    // 检查是否包含非Base64字符
    const base64Regex = /^[A-Za-z0-9+/=]+$/;
    if (!base64Regex.test(base64Data)) {
      console.warn('[TTSStreamService] Base64数据包含非法字符');
      
      // 尝试清理非法字符
      const cleanedBase64 = base64Data.replace(/[^A-Za-z0-9+/=]/g, '');
      if (cleanedBase64.length < base64Data.length * 0.9) {
        // 如果清理后的数据长度减少了10%以上，认为数据已损坏
        console.error('[TTSStreamService] Base64数据严重损坏');
        return false;
      }
      
      // 返回false，让调用者使用fixBase64Padding方法修复
      return false;
    }
    
    // 检查长度是否是4的倍数（标准Base64要求）
    if (base64Data.length % 4 !== 0) {
      console.warn('[TTSStreamService] Base64数据长度不是4的倍数');
      return false;
    }
    
    // 简化填充字符检查，只检查基本规则
    const paddingChar = '=';
    const paddingIndex = base64Data.indexOf(paddingChar);
    if (paddingIndex > -1) {
      // 填充字符只能出现在末尾
      if (paddingIndex < base64Data.length - 2) {
        console.warn('[TTSStreamService] Base64填充字符位置不正确');
        return false;
      }
    }
    
    return true;
  }
  
  /**
   * 修复Base64字符串的填充
   * @param {string} base64Data - Base64编码的字符串
   * @returns {string} - 修复后的Base64字符串
   * @private
   */
  fixBase64Padding(base64Data) {
    if (!base64Data || typeof base64Data !== 'string') {
      console.error('[TTSStreamService] 无法修复空或非字符串的Base64数据');
      return '';
    }
    
    try {
      // 首先清理所有非Base64字符
      let cleanedBase64 = base64Data.replace(/[^A-Za-z0-9+/=]/g, '');
      
      // 移除所有现有的填充字符
      cleanedBase64 = cleanedBase64.replace(/=/g, '');
      
      // 计算需要的填充字符数量
      const paddingNeeded = (4 - (cleanedBase64.length % 4)) % 4;
      
      // 添加正确数量的填充字符
      const fixedBase64 = cleanedBase64 + '='.repeat(paddingNeeded);
      
      console.log(`[TTSStreamService] Base64数据修复: 原始长度=${base64Data.length}, 清理后长度=${cleanedBase64.length}, 修复后长度=${fixedBase64.length}`);
      
      return fixedBase64;
    } catch (error) {
      console.error('[TTSStreamService] 修复Base64数据时出错:', error);
      
      // 更强健的错误恢复：尝试保留原始数据中的有效部分
      try {
        // 保留原始数据中的有效Base64字符
        const validChars = base64Data.replace(/[^A-Za-z0-9+/=]/g, '');
        
        // 移除所有填充字符
        const withoutPadding = validChars.replace(/=/g, '');
        
        // 重新添加正确的填充
        const paddingNeeded = (4 - (withoutPadding.length % 4)) % 4;
        return withoutPadding + '='.repeat(paddingNeeded);
      } catch (fallbackError) {
        console.error('[TTSStreamService] 备用修复方法也失败:', fallbackError);
        // 最后的尝试：截断到4的倍数长度
        const length = Math.floor(base64Data.length / 4) * 4;
        return base64Data.substring(0, length);
      }
    }
  }
  
  /**
   * 使用临时文件播放音频
   * @param {string} base64Data - Base64编码的音频数据
   * @returns {Promise<boolean>} - 是否成功播放
   */
  playAudioWithTempFile(base64Data) {
    console.log('[TTSStreamService] 使用临时文件播放音频');
    
    // 如果已经在播放，先停止当前播放
    if (this.isPlaying) {
      this.stopPlayback();
    }
    
    return new Promise((resolve, reject) => {
      try {
        // 首先尝试使用文件系统API播放
        this.playWithFileSystem(base64Data, resolve, reject)
          .catch(error => {
            console.warn('[TTSStreamService] 文件系统播放失败，尝试直接播放方式:', error);
            
            // 如果文件系统方法失败，尝试直接播放方式
            this.playWithDirectMethod(base64Data, resolve, reject)
              .catch(directError => {
                console.error('[TTSStreamService] 直接播放方式也失败:', directError);
                reject(directError);
              });
          });
      } catch (error) {
        console.error('[TTSStreamService] 播放音频过程中出错:', error);
        reject(error);
      }
    });
  }
  
  /**
   * 使用文件系统API播放音频
   * @param {string} base64Data - Base64编码的音频数据
   * @param {Function} resolve - Promise解析函数
   * @param {Function} reject - Promise拒绝函数
   * @returns {Promise<void>}
   * @private
   */
  async playWithFileSystem(base64Data, resolve, reject) {
    console.log('[TTSStreamService] 尝试使用文件系统API播放音频');
    
    // 检查并修复Base64数据
    if (base64Data.startsWith('data:audio')) {
      // 如果是data URI格式，提取Base64部分
      base64Data = base64Data.split(',')[1];
    }
    
    // 确保Base64字符串有效
    if (!this.isValidBase64(base64Data)) {
      console.warn('[TTSStreamService] 检测到无效的Base64数据，尝试修复');
      base64Data = this.fixBase64Padding(base64Data);
      
      // 如果仍然无效，直接使用直接播放方式
      if (!this.isValidBase64(base64Data)) {
        console.warn('[TTSStreamService] 无法修复Base64数据，切换到直接播放方式');
        return this.playWithDirectMethod(base64Data, resolve, reject);
      }
    }
    
    try {
      // 估算文件大小
      const estimatedSize = Math.ceil(base64Data.length * 0.75); // Base64编码的数据大约是原始数据的4/3
      console.log(`[TTSStreamService] 估计音频数据大小: ${estimatedSize} 字节`);
      
      // 创建临时文件路径
      const tempFilePath = `http://usr/t${Date.now()}.mp3`;
      console.log(`[TTSStreamService] 临时文件路径: ${tempFilePath}`);
      
      // 将Base64转换为ArrayBuffer
      let arrayBuffer;
      try {
        arrayBuffer = wx.base64ToArrayBuffer(base64Data);
        console.log(`[TTSStreamService] Base64转换为ArrayBuffer成功，大小: ${arrayBuffer.byteLength}`);
      } catch (error) {
        console.error('[TTSStreamService] Base64转换为ArrayBuffer失败:', error);
        // 如果转换失败，尝试直接播放方式
        return this.playWithDirectMethod(base64Data, resolve, reject);
      }
      
      // 在写入文件前清理旧的临时文件，释放存储空间
      try {
        await this.cleanupOldTempFiles();
      } catch (cleanupError) {
        console.warn('[TTSStreamService] 清理旧临时文件失败:', cleanupError);
        // 继续尝试写入，即使清理失败
      }
      
      // 写入文件
      try {
        await new Promise((fileResolve, fileReject) => {
          wx.getFileSystemManager().writeFile({
            filePath: tempFilePath,
            data: arrayBuffer,
            encoding: 'binary',
            success: () => {
              console.log('[TTSStreamService] 文件写入成功:', tempFilePath);
              fileResolve();
            },
            fail: (err) => {
              console.error('[TTSStreamService] 写入文件失败:', err);
              fileReject(err);
            }
          });
        });
      } catch (writeError) {
        // 如果是存储空间不足错误，尝试更积极地清理和直接播放
        if (writeError && writeError.errMsg && writeError.errMsg.includes('storage limit')) {
          console.warn('[TTSStreamService] 存储空间不足，尝试清理后使用直接播放方式');
          
          // 尝试清理更多文件
          try {
            await this.cleanupAllTempFiles();
          } catch (error) {
            console.warn('[TTSStreamService] 清理所有临时文件失败:', error);
          }
          
          // 切换到直接播放方式
          return this.playWithDirectMethod(base64Data, resolve, reject);
        } else {
          // 其他错误，也尝试直接播放方式
          console.error('[TTSStreamService] 写入文件失败，切换到直接播放方式:', writeError);
          return this.playWithDirectMethod(base64Data, resolve, reject);
        }
      }
      
      // 创建音频上下文
      this.currentAudioContext = wx.createInnerAudioContext();
      this.isPlaying = true;
      
      // 设置音频源
      this.currentAudioContext.src = tempFilePath;
      
      // 设置事件处理器
      this.currentAudioContext.onPlay(() => {
        console.log('[TTSStreamService] 开始播放音频');
        if (this.callbacks.onStart) {
          this.callbacks.onStart();
        }
      });
      
      this.currentAudioContext.onEnded(() => {
        console.log('[TTSStreamService] 音频播放结束');
        
        // 清理资源
        this.isPlaying = false;
        if (this.currentAudioContext) {
          this.currentAudioContext.destroy();
          this.currentAudioContext = null;
        }
        
        // 删除临时文件
        this.deleteTempFile(tempFilePath);
        
        // 触发结束回调
        if (this.callbacks.onEnd) {
          this.callbacks.onEnd();
        }
        
        resolve(true);
      });
      
      this.currentAudioContext.onError((err) => {
        console.error('[TTSStreamService] 音频播放错误:', err);
        
        // 清理资源
        this.isPlaying = false;
        if (this.currentAudioContext) {
          this.currentAudioContext.destroy();
          this.currentAudioContext = null;
        }
        
        // 删除临时文件
        this.deleteTempFile(tempFilePath);
        
        // 触发错误回调
        if (this.callbacks.onError) {
          this.callbacks.onError(err);
        }
        
        // 尝试使用直接播放方式
        console.warn('[TTSStreamService] 文件播放失败，尝试直接播放方式');
        this.playWithDirectMethod(base64Data, resolve, reject);
      });
      
      // 播放音频
      this.currentAudioContext.play();
      
    } catch (error) {
      console.error('[TTSStreamService] 使用文件系统API播放音频时出错:', error);
      
      // 清理资源
      this.isPlaying = false;
      if (this.currentAudioContext) {
        this.currentAudioContext.destroy();
        this.currentAudioContext = null;
      }
      
      // 尝试使用直接播放方式
      console.warn('[TTSStreamService] 捕获到错误，尝试直接播放方式');
      this.playWithDirectMethod(base64Data, resolve, reject);
    }
  }
  
  /**
   * 删除临时文件
   * @param {string} filePath - 文件路径
   * @private
   */
  deleteTempFile(filePath) {
    try {
      wx.getFileSystemManager().unlink({
        filePath: filePath,
        success: () => {
          console.log('[TTSStreamService] 临时文件删除成功:', filePath);
        },
        fail: (error) => {
          console.warn('[TTSStreamService] 临时文件删除失败:', error);
        }
      });
    } catch (error) {
      console.warn('[TTSStreamService] 删除临时文件出错:', error);
    }
  }
  
  /**
   * 清理旧的临时文件
   * @private
   */
  cleanupOldTempFiles() {
    try {
      const fs = wx.getFileSystemManager();
      const userPath = wx.env.USER_DATA_PATH;
      
      // 列出用户目录下的文件
      fs.readdir({
        dirPath: userPath,
        success: (res) => {
          const files = res.files || [];
          const now = Date.now();
          let cleanedCount = 0;
          
          // 查找并删除超过5分钟的临时音频文件
          files.forEach(file => {
            if (file.startsWith('t') && file.endsWith('.mp3')) {
              try {
                // 尝试从文件名中提取时间戳
                const timestamp = parseInt(file.substring(1, file.indexOf('.')));
                
                // 如果文件超过5分钟，或者无法解析时间戳，则删除
                if (isNaN(timestamp) || (now - timestamp) > 5 * 60 * 1000) {
                  fs.unlink({
                    filePath: `${userPath}/${file}`,
                    success: () => {
                      cleanedCount++;
                      console.log(`[TTSStreamService] 已删除旧临时文件: ${file}`);
                    },
                    fail: (err) => {
                      console.warn(`[TTSStreamService] 删除文件失败: ${file}`, err);
                    }
                  });
                }
              } catch (e) {
                console.warn(`[TTSStreamService] 处理文件时出错: ${file}`, e);
              }
            }
          });
          
          console.log(`[TTSStreamService] 清理了${cleanedCount}个旧临时文件`);
        },
        fail: (err) => {
          console.warn('[TTSStreamService] 读取目录失败:', err);
        }
      });
    } catch (e) {
      console.warn('[TTSStreamService] 清理临时文件出错:', e);
    }
  }
  
  /**
   * 清理所有临时音频文件
   * @private
   */
  cleanupAllTempFiles() {
    try {
      const fs = wx.getFileSystemManager();
      const userPath = wx.env.USER_DATA_PATH;
      
      // 列出用户目录下的文件
      fs.readdir({
        dirPath: userPath,
        success: (res) => {
          const files = res.files || [];
          let cleanedCount = 0;
          
          // 删除所有临时音频文件
          files.forEach(file => {
            if (file.endsWith('.mp3')) {
              fs.unlink({
                filePath: `${userPath}/${file}`,
                success: () => {
                  cleanedCount++;
                  console.log(`[TTSStreamService] 已删除临时文件: ${file}`);
                },
                fail: (err) => {
                  console.warn(`[TTSStreamService] 删除文件失败: ${file}`, err);
                }
              });
            }
          });
          
          console.log(`[TTSStreamService] 清理了${cleanedCount}个临时文件`);
        },
        fail: (err) => {
          console.warn('[TTSStreamService] 读取目录失败:', err);
        }
      });
    } catch (e) {
      console.warn('[TTSStreamService] 清理临时文件出错:', e);
    }
  }
  
  /**
   * 使用直接方法播放音频（不使用文件系统）
   * @param {string} base64Data - Base64编码的音频数据
   * @param {Function} resolve - Promise解析函数
   * @param {Function} reject - Promise拒绝函数
   * @private
   */
  playWithDirectMethod(base64Data, resolve, reject) {
    console.log('[TTSStreamService] 尝试使用直接方法播放音频');
    
    try {
      // 确保Base64数据有效
      if (!this.isValidBase64(base64Data)) {
        console.warn('[TTSStreamService] 无效的Base64数据，尝试修复');
        base64Data = this.fixBase64Padding(base64Data);
      }
      
      // 创建数据URI
      const dataURI = `data:audio/mp3;base64,${base64Data}`;
      
      // 创建新的音频上下文
      this.currentAudioContext = wx.createInnerAudioContext();
      this.isPlaying = true;
      
      // 设置音频事件
      this.currentAudioContext.onPlay(() => {
        console.log('[TTSStreamService] 开始播放音频(直接方法)');
        if (this.callbacks.onStart) {
          this.callbacks.onStart();
        }
      });
      
      this.currentAudioContext.onEnded(() => {
        console.log('[TTSStreamService] 音频播放结束(直接方法)');
        
        // 清理资源
        this.isPlaying = false;
        if (this.currentAudioContext) {
          this.currentAudioContext.destroy();
          this.currentAudioContext = null;
        }
        
        if (this.callbacks.onEnd) {
          this.callbacks.onEnd();
        }
        
        // 重要：确保解析Promise，让调用者知道播放已完成
        resolve(true);
      });
      
      this.currentAudioContext.onError((err) => {
        console.error('[TTSStreamService] 音频播放错误(直接方法):', err);
        
        // 清理资源
        this.isPlaying = false;
        if (this.currentAudioContext) {
          this.currentAudioContext.destroy();
          this.currentAudioContext = null;
        }
        
        // 触发错误回调
        if (this.callbacks.onError) {
          this.callbacks.onError(err);
        }
        
        reject(err);
      });
      
      // 尝试使用微信的createBufferURL API
      try {
        // 将Base64转换为ArrayBuffer
        const arrayBuffer = wx.base64ToArrayBuffer(base64Data);
        
        // 创建临时URL
        const tempUrl = wx.createBufferURL(arrayBuffer);
        console.log('[TTSStreamService] 创建临时URL成功:', tempUrl);
        
        // 设置音频源
        this.currentAudioContext.src = tempUrl;
        
        // 播放音频
        this.currentAudioContext.play();
        
        // 重新设置onEnded回调，确保包含URL释放逻辑
        this.currentAudioContext.onEnded = () => {
          console.log('[TTSStreamService] 音频播放结束(BufferURL方法)');
          
          // 清理资源
          this.isPlaying = false;
          if (this.currentAudioContext) {
            this.currentAudioContext.destroy();
            this.currentAudioContext = null;
          }
          
          // 释放临时URL
          wx.revokeBufferURL(tempUrl);
          
          if (this.callbacks.onEnd) {
            this.callbacks.onEnd();
          }
          
          // 重要：确保解析Promise，让调用者知道播放已完成
          resolve(true);
        };
      } catch (bufferError) {
        console.error('[TTSStreamService] BufferURL方法失败:', bufferError);
        
        // 尝试直接使用dataURI
        try {
          // 设置音频源
          this.currentAudioContext.src = dataURI;
          console.log('[TTSStreamService] 设置音频源(DataURI方法)');
          
          // 播放音频
          this.currentAudioContext.play();
        } catch (uriError) {
          console.error('[TTSStreamService] DataURI方法失败:', uriError);
          reject(uriError);
        }
      }
    } catch (error) {
      console.error('[TTSStreamService] 直接播放方法失败:', error);
      reject(error);
    }
  }
  
  /**
   * 流式合成并播放
   * @param {string} text - 要合成的文本
   * @param {string} messageId - 消息ID，用于缓存
   * @param {boolean} silent - 是否静默模式（不显示加载提示）
   * @param {boolean} isSegment - 是否是分段处理的一部分
   * @returns {Promise<boolean>} - 是否成功
   */
  async streamSynthesizeAndPlay(text, messageId, silent = false, isSegment = false) {
    console.log(`[TTSStreamService] 开始流式合成并播放, 消息ID: ${messageId}, 文本长度: ${text.length}, 静默: ${silent}, 分段: ${isSegment}`);
    
    try {
      // 如果已经在播放，先停止当前播放
      if (this.isPlaying && !isSegment) {
        this.stopPlayback();
      }
      
      // 检查是否已经缓存
      if (messageId && this.audioCache[messageId] && !isSegment) {
        console.log(`[TTSStreamService] 使用缓存的音频数据, 消息ID: ${messageId}`);
        const success = await this.playAudio([this.audioCache[messageId]]);
        
        // 触发开始回调
        if (success && this.callbacks.onStart && !silent) {
          this.callbacks.onStart();
        }
        
        return success;
      }
      
      // 开始新的合成
      try {
        // 如果是分段，添加额外的日志
        if (isSegment) {
          console.log(`[TTSStreamService] 处理分段文本, 消息ID: ${messageId}, 文本: "${text.substring(0, 20)}${text.length > 20 ? '...' : ''}"`);
        }
        
        const audioChunks = await this.streamSynthesize(text, messageId, silent);
        
        // 检查是否有有效的音频块
        if (!audioChunks || audioChunks.length === 0) {
          console.warn(`[TTSStreamService] 未获取到有效音频数据, 消息ID: ${messageId}`);
          return false;
        }
        
        console.log(`[TTSStreamService] 合成完成，开始播放, 消息ID: ${messageId}, 音频块数: ${audioChunks.length}`);
        
        // 保存原始回调
        const originalOnEnd = this.callbacks.onEnd;
        
        // 如果是分段处理，临时修改onEnd回调，避免清除播放状态
        if (isSegment) {
          this.callbacks.onEnd = () => {
            console.log(`[TTSStreamService] 分段播放结束，不清除播放状态, 消息ID: ${messageId}`);
            // 不调用原始的onEnd回调，避免清除播放状态
            
            // 但仍然需要触发播放结束事件，以便上层知道这段已经播放完成
            if (this.callbacks.onSegmentEnd) {
              this.callbacks.onSegmentEnd(messageId);
            }
          };
        }
        
        // 播放合成的音频
        const success = await this.playAudio(audioChunks);
        
        // 恢复原始回调
        if (isSegment) {
          this.callbacks.onEnd = originalOnEnd;
        }
        
        // 触发开始回调（如果不是静默模式）
        if (success && this.callbacks.onStart && !silent) {
          this.callbacks.onStart();
        }
        
        // 缓存分段音频（即使是分段，也单独缓存每一段）
        if (success && messageId && audioChunks.length > 0) {
          const combinedAudio = audioChunks.join('');
          if (combinedAudio && combinedAudio.length > 0) {
            console.log(`[TTSStreamService] 缓存分段音频, 消息ID: ${messageId}, 大小: ${combinedAudio.length}`);
            this.audioCache[messageId] = combinedAudio;
          }
        }
        
        return success;
      } catch (error) {
        console.error(`[TTSStreamService] 流式合成失败, 消息ID: ${messageId}:`, error);
        
        // 确保隐藏加载提示
        if (!silent) {
          wx.hideLoading();
        }
        
        // 触发错误回调
        if (this.callbacks.onError) {
          this.callbacks.onError(error);
        }
        
        return false;
      }
    } catch (error) {
      console.error(`[TTSStreamService] 流式合成并播放过程中出错, 消息ID: ${messageId}:`, error);
      
      // 确保隐藏加载提示
      if (!silent) {
        wx.hideLoading();
      }
      
      // 触发错误回调
      if (this.callbacks.onError) {
        this.callbacks.onError(error);
      }
      
      return false;
    }
  }
  
  /**
   * 从缓存播放音频
   * @param {string} messageId - 消息ID
   * @returns {Promise<boolean>} - 是否成功播放
   */
  async playFromCache(messageId) {
    console.log(`[TTSStreamService] 尝试从缓存播放, 消息ID: ${messageId}`);
    
    // 如果已经在播放，先停止当前播放
    if (this.isPlaying) {
      this.stopPlayback();
    }
    
    // 检查是否是分段消息ID (格式: originalId-segX)
    const isSegment = messageId.includes('-seg');
    let baseMessageId = messageId;
    
    if (isSegment) {
      // 提取基础消息ID
      baseMessageId = messageId.split('-seg')[0];
      console.log(`[TTSStreamService] 检测到分段消息ID, 基础ID: ${baseMessageId}`);
    }
    
    // 检查缓存是否存在
    if (!messageId || !this.audioCache[messageId]) {
      // 如果是分段消息，尝试查找原始消息的缓存
      if (isSegment && this.audioCache[baseMessageId]) {
        console.log(`[TTSStreamService] 分段缓存不存在，但找到了基础消息缓存: ${baseMessageId}`);
        // 使用基础消息的缓存
        messageId = baseMessageId;
      } else {
        console.warn(`[TTSStreamService] 缓存中不存在消息ID: ${messageId}`);
        return false;
      }
    }
    
    try {
      console.log(`[TTSStreamService] 从缓存播放, 消息ID: ${messageId}, 数据长度: ${this.audioCache[messageId].length}`);
      
      // 播放缓存的音频
      const success = await this.playAudio([this.audioCache[messageId]]);
      
      // 触发开始回调
      if (success && this.callbacks.onStart) {
        this.callbacks.onStart();
      }
      
      return success;
    } catch (error) {
      console.error(`[TTSStreamService] 从缓存播放失败, 消息ID: ${messageId}:`, error);
      
      // 触发错误回调
      if (this.callbacks.onError) {
        this.callbacks.onError(error);
      }
      
      // 如果播放失败，可能是缓存损坏，清除缓存
      delete this.audioCache[messageId];
      
      return false;
    }
  }
  
  /**
   * 停止播放
   */
  stop() {
    // 停止流式合成
    this.stopStreaming();
    
    // 停止播放
    this.stopPlayback();
    
    // 确保隐藏加载提示
    try {
      wx.hideLoading();
    } catch (e) {
      console.warn('[TTSStreamService] 隐藏加载提示失败:', e);
    }
    
    console.log('[TTSStreamService] 已停止所有合成和播放');
  }
  
  /**
   * 清除指定消息ID的缓存
   * @param {string} messageId - 消息ID
   */
  clearCache(messageId) {
    if (messageId && this.audioCache[messageId]) {
      delete this.audioCache[messageId];
    }
  }
  
  /**
   * 清除所有缓存
   */
  clearAllCache() {
    this.audioCache = {};
  }
  
  /**
   * 获取缓存大小
   * @returns {number} - 缓存中的条目数
   */
  getCacheSize() {
    return Object.keys(this.audioCache).length;
  }
  
  /**
   * 工具方法：根据错误码获取友好的错误提示
   * @param {number|string} errorCode - API返回的错误码
   * @returns {string} - 对应的错误提示文本
   */
  getErrorMessage(errorCode) {
    const errorMessages = {
      40402003: '提交文本长度超过限制',
      45000000: '音色鉴权失败，请检查音色权限',
      55000000: '服务端错误，请稍后重试',
      'REQUEST_ERROR': '网络请求失败，请检查网络连接',
      'HTTP_ERROR': '服务器响应异常，请稍后重试',
      'TIMEOUT': '请求超时，请检查网络连接'
    };
    return errorMessages[errorCode] || '发生未知错误，请重试';
  }
} 